//
// Created by Administrator on 2021/7/31.
//

#ifndef OPENGLLEARN_QUATERNION_H
#define OPENGLLEARN_QUATERNION_H

class Quaternion
{
    // ctor
    Quaternion() : Quaternion(0, 0, 0, 0) {}
    Quaternion(float w, float x, float y, float z)
        : w_{w}, x_{x}, y_{y}, z_{z} {}
    Quaternion(const Quaternion& rhs) = default;
    Quaternion(Quaternion&& rhs) = default;

    // functions
    inline float Norm();
    inline void Conjugate();
    inline Quaternion Conjugated();
    inline void Invert();
    inline Quaternion Inverse();

    // static functions
    static Quaternion Log(const Quaternion& q);
    static Quaternion Exp(const Quaternion& q);
    static Quaternion Pow(const Quaternion& q, float exponent);
    static Quaternion Slerp(const Quaternion& a, const Quaternion& b, const float& t);

    // operators
    Quaternion& operator= (const Quaternion& rhs) = default;
    Quaternion& operator= (Quaternion&& rhs) = default;

    Quaternion& operator+= (const Quaternion& rhs)
    {
        w() += rhs.w();
        x() += rhs.x();
        y() += rhs.y();
        z() += rhs.z();

        return *this;
    }
    Quaternion operator+ (const Quaternion& rhs) const
    {
        return {
                w() + rhs.w(),
                x() + rhs.x(),
                y() + rhs.y(),
                z() + rhs.z(),
        };
    }
    Quaternion& operator*= (const float& rhs)
    {
        w() *= rhs;
        x() *= rhs;
        y() *= rhs;
        z() *= rhs;

        return *this;
    }
    Quaternion operator* (const float& rhs) const
    {
        return {
            w() * rhs,
            x() * rhs,
            y() * rhs,
            z() * rhs,
        };
    }

    float& w() { return x_; }
    float& x() { return x_; }
    float& y() { return y_; }
    float& z() { return z_; }
    const float& w() const { return x_; }
    const float& x() const { return x_; }
    const float& y() const { return y_; }
    const float& z() const { return z_; }

private:
    float w_;
    float x_;
    float y_;
    float z_;
};

#endif //OPENGLLEARN_QUATERNION_H
